#include <cutils/log.h>
#include <fcntl.h>
#include "Dload.h"
#include "communication.h"
//#include "fdl.h"
#include "bmpacket.h"
#include "PacFile.h"
#include "calibration.h"
#include "compatible.h"

#define PKT_TYPE_POS       0x00
#define PKT_LEN_POS        0x02
#define PKT_DATA_POS       0x04

#define MAX_LOG_LEN 256
#define START_BSL_PKT_LEN (PACHET_HDR_LEN + 2 * sizeof(DWORD))
#define ERASE_FLASH_PKT_LEN  (PACHET_HDR_LEN + 2 * sizeof(DWORD)) 

#define SECTOR_SIZE			512
#define SMALL_PAGE		0
#define LARGE_PAGE		1

typedef struct _OS_INFO {
	char    Name[24];
	char    Description[48];
	char	Version[24];
	unsigned short	Offset;  // in sectors
	unsigned short	Size;    // in sectors
} OS_INFO/*, * POS_INFO*/;

typedef struct _BOOT_PARAM {
	unsigned char	Magic[4];
	unsigned short  Size;
	unsigned short  TotalSize;
	long	        TimeStamp;
	unsigned char	TraceOn;
	unsigned char	Reserved;
	unsigned char	CurrentOS;
	unsigned char	NumOfOS;
	unsigned short  SizeOfOSInfo;
	unsigned short  OSOffset;
} BOOT_PARAM/*, * PBOOT_PARAM*/;
/*lint -restore */

static const unsigned char MAGIC[] = { 'S', 'T', 'B', 'P' };

BOOL m_bBigEndian = TRUE;
BOOL m_bStopOpr = 0;
BOOL m_bCheckBaudRate = 0;
BOOL m_bCheckCrc = 0;
BOOL m_bNVHasCheckSum = 0; // nv
BYTE* m_lpCurrRead = NULL;
BYTE m_szMCP[MAX_PATH];
UINT m_nSectSize = 0;
UINT m_uiReadOffset = 0;
DWORD m_dwLastPktSize = 0;


LPBYTE m_lpReceiveBuffer = NULL;
DWORD m_dwReceiveLen = 0;
DWORD m_dwBufferSize = 0;

#define MAX_RECV_LEN (0x8000) 
BYTE m_RecvData[ MAX_RECV_LEN ];
int m_ulRecvDataLen;


BOOL StopOpr()
{
	m_bStopOpr = 1;
	return 1;
}


BOOL ProcessData( LPBYTE lpData, int iDataLen )
{
	int nRet = 0;
	int     iRecvDataLen;
    LPBYTE  lpRecvData = NULL;
    int     iDecodeDataLen = 0;
    LPBYTE  lpDecodeData = NULL;
    BOOL    bReturnCode = TRUE;
	P_Packet_Header tmpPktHeader;

   //if( m_dwLastErrorCode != 0  && m_dwLastErrorCode != BSL_REP_INCOMPLETE_DATA)//have error occured.
   //     return FALSE;


    
    lpRecvData = lpData;
    iRecvDataLen = iDataLen;
    
    lpDecodeData = NULL;

    if( iRecvDataLen > MAX_RECV_LEN )
    {
        ALOGE("receiving packet BSL_REP_TOO_MUCH_DATA.");
        m_dwLastErrorCode = BSL_REP_TOO_MUCH_DATA;
        return FALSE;        
    }

    if( m_ulRecvDataLen + iRecvDataLen > MAX_RECV_LEN )
    {
        memset( m_RecvData, 0 , MAX_RECV_LEN );
        m_ulRecvDataLen = 0;   
        ALOGE("receiving packet occurs error.");
    }

    memcpy( m_RecvData + m_ulRecvDataLen, lpRecvData, iRecvDataLen );
    m_ulRecvDataLen += iRecvDataLen;

    ALOGE("ProcessData m_ulRecvDataLen=%d", m_ulRecvDataLen);

    nRet = decode_bmmsg( m_RecvData, m_ulRecvDataLen,
                        &lpDecodeData, &iDecodeDataLen,m_bCheckCrc);
    if( nRet >= PART_PACKET )
    {
        if( nRet > PART_PACKET )
        {
            m_ulRecvDataLen -= nRet - PART_PACKET;
            memmove( m_RecvData, m_RecvData + nRet - PART_PACKET, 
                m_ulRecvDataLen );
        }
        ALOGE("incomplete frame");
        //m_pChannel->FreeMem( lpData );
        m_dwLastErrorCode = BSL_REP_INCOMPLETE_DATA;
        return FALSE;
    }

    memset( m_RecvData, 0 , MAX_RECV_LEN );
    m_ulRecvDataLen = 0;
    //m_pChannel->FreeMem( lpData );

    if( nRet == ERROR_PACKET )
    {   
        ALOGE("ERROR_PACKET frame");
        m_dwLastErrorCode = BSL_REP_DECODE_ERROR;
        return FALSE;
    }       

    tmpPktHeader = (P_Packet_Header)lpDecodeData;
    
    //Convert the data header
    if(TRUE == m_bBigEndian)
    {        
        short SoruceValue, DestValue;
        
        SoruceValue = tmpPktHeader->PacketType;
        DestValue   = 0;      
        CONVERT_SHORT(SoruceValue, DestValue);      
        tmpPktHeader->PacketType = DestValue;
        
        SoruceValue = tmpPktHeader->DataSize;
        DestValue   = 0;      
        CONVERT_SHORT(SoruceValue, DestValue);      
        tmpPktHeader->DataSize = DestValue;
    }
    
    m_dwLastErrorCode = tmpPktHeader->PacketType;
    bReturnCode = FALSE;
    
	if(tmpPktHeader->PacketType == BSL_REP_VERIFY_ERROR)
    {
		ALOGE("Packet Verify.");
        bReturnCode = FALSE;
    }    
    else if(tmpPktHeader->PacketType == BSL_REP_ACK)
    {
        ALOGE("BSL_REP_ACK");
        bReturnCode = TRUE;
    }
    else if(tmpPktHeader->PacketType == BSL_REP_VER)
    {
        bReturnCode = TRUE;
    }    
    else if(tmpPktHeader->PacketType == BSL_REP_READ_FLASH)
    {
        ALOGE("BSL_REP_READ_FLASH");
        bReturnCode = TRUE;
        if( NULL != lpDecodeData  &&  m_iLastSentPktType == BSL_CMD_READ_FLASH )
        {
            // The buffer is read from module
            if( iDecodeDataLen <= PACHET_HDR_LEN  ||
                m_dwLastPktSize != iDecodeDataLen - PACHET_HDR_LEN)
            {
                // Data read error
                free(lpDecodeData);
                lpDecodeData = NULL;
                m_dwLastErrorCode = BSL_REP_OPERATION_FAILED;
                return FALSE;
            }
            if( m_lpReceiveBuffer != NULL )
            {
                if( m_dwReceiveLen + iDecodeDataLen - PACHET_HDR_LEN - m_uiReadOffset <= m_dwBufferSize  )
                {
                    memcpy( m_lpReceiveBuffer + m_dwReceiveLen,
                        lpDecodeData + PACHET_HDR_LEN + m_uiReadOffset,
                        iDecodeDataLen - PACHET_HDR_LEN - m_uiReadOffset );
                    m_dwReceiveLen += ( iDecodeDataLen - PACHET_HDR_LEN - m_uiReadOffset );
                    m_uiReadOffset = 0;
                }
            }
        }

    } else if( tmpPktHeader->PacketType == BSL_REP_READ_CHIP_TYPE || 
        tmpPktHeader->PacketType == BSL_REP_LOOKUP_NVITEM )
    {        
        bReturnCode = TRUE; 
        if(  NULL != lpDecodeData  )
        {
            
        }
    }
	else if( tmpPktHeader->PacketType == BSL_REP_READ_SECTOR_SIZE)
    {        
        bReturnCode = TRUE; 
        if(  NULL != lpDecodeData  )
        {
			m_nSectSize = 0;
			m_nSectSize = *(int*)(lpDecodeData+PKT_DATA_POS);
        }
    }    
    else if( tmpPktHeader->PacketType == BSL_REP_READ_MCP_TYPE)
    {        
        bReturnCode = TRUE; 
        if(  NULL != lpDecodeData  )
        {
			memset(m_szMCP, 0, MAX_PATH);
			memcpy(m_szMCP, lpDecodeData+PKT_DATA_POS, iDecodeDataLen-PKT_DATA_POS);
        }
    }
    // <-
    // xucanhua.28 ->
    else if( tmpPktHeader->PacketType == BSL_CMD_FDL_VER)
    {        
        bReturnCode = TRUE; 
        
        if(  NULL != lpDecodeData  )
        {
            
        }
    }
    else if( tmpPktHeader->PacketType == BSL_REP_VER_ERROR)
    {        
        bReturnCode = FALSE; 
        m_dwLastErrorCode = BSL_REP_VER_ERROR;
        if(  NULL != lpDecodeData  )
        {
            
        }
    }
    // <-


    if( NULL != lpDecodeData )
    {      
        free(lpDecodeData);
        lpDecodeData = NULL;
    }    

    return bReturnCode;    
}

BOOL ReadPacket(int nTime)
{
	int nReadLen = 0;
	BYTE szBuf[MAX_RECV_LEN] = {0};
	nReadLen = read_com(szBuf, MAX_RECV_LEN, nTime);
	if (nReadLen > 0)
	{
		return ProcessData(szBuf, nReadLen);
	}   

	return 0;	
}

BOOL SendData( LPBYTE lpData, 
                            int iDataSize, 
                            BOOL bNoCheckBaud /* = TRUE */,
                            DWORD dwTimeout /* = 1000  */ )
{
    LPBYTE lpSendData = NULL;
    int    iSendDataLen = 0;
        
    //Save the last send packet type
    m_iLastSentPktType = (CMD_TYPE)( lpData[PKT_TYPE_POS] ); 
	ALOGE("m_iLastSentPktType = %x dwTimeout = %d",m_iLastSentPktType ,dwTimeout);
    if( m_iLastSentPktType == BSL_CMD_MIDST_DATA || m_iLastSentPktType == BSL_CMD_END_DATA )
    {
        if( m_dwLastErrorCode == BSL_REP_DOWN_DEST_ERROR )
        {
            return FALSE;
        }
    }
    
    //Convert the data header
    if(TRUE == m_bBigEndian )
    {
        P_Packet_Header tmpPktHeader = (P_Packet_Header)lpData;
        
        short SoruceValue, DestValue;
        
        SoruceValue = tmpPktHeader->PacketType;
        DestValue   = 0;      
        CONVERT_SHORT(SoruceValue, DestValue);      
        tmpPktHeader->PacketType = DestValue;
        
        SoruceValue = tmpPktHeader->DataSize;
        DestValue   = 0;      
        CONVERT_SHORT(SoruceValue, DestValue);      
        tmpPktHeader->DataSize = DestValue;
    }
    
    if( bNoCheckBaud )
    {
        if(!encode_bmmsg( lpData, iDataSize, &lpSendData, &iSendDataLen, m_bCheckCrc))
        {
            ALOGE("Encode message fail.");
            return FALSE;
        }        
    }
    else
    {
        lpSendData    = lpData;
        iSendDataLen = iDataSize;
    }
    
    m_dwLastErrorCode = 0;
    m_bOperationSuccess = FALSE;

    if( iSendDataLen != (int)(mDownloadCallback.onWriteCom( lpSendData, iSendDataLen )) )
    {
        if((bNoCheckBaud) && (lpSendData))
        {
            free(lpSendData);
        }
		m_dwLastErrorCode = BSL_UART_SEND_ERROR;
        ALOGE( "Write channel fail.");
        return FALSE;
    } 

    if((bNoCheckBaud) && (lpSendData) && m_iLastSentPktType != BSL_CMD_READ_FLASH )
    {
        free(lpSendData);
    }
        
    memset( m_RecvData, 0 , MAX_RECV_LEN );
    m_ulRecvDataLen = 0;  
    
    if (m_iLastSentPktType != 0x7E)
        dwTimeout = 100;
	do 
	{
		if (ReadPacket(dwTimeout))
		{
			if (m_iLastSentPktType == 0x7E)
			{
				m_bOperationSuccess = TRUE;
			}
			return TRUE;
		   // break;
		}
		usleep(50);
		dwTimeout-=10;
	} while (dwTimeout > 0);



    if( m_iLastSentPktType == BSL_CMD_READ_FLASH )
    {
        /*if( !m_bOperationSuccess )
        {
            m_dwLastErrorCode = 0;
            m_bOperationSuccess = FALSE;

            
            ALOGE("Repeat send read flash command.");
            
            
            //if( iSendDataLen != (int)(write_com( lpSendData, iSendDataLen )) )
            //{
            //    if((bNoCheckBaud) && (lpSendData))
            //    {
            //        free(lpSendData);
            //    }
            //    ALOGE( "Write channel fail." );
            //    return FALSE;
            //}
            
            
            if((bNoCheckBaud) && (lpSendData))
            {
                free(lpSendData);
            }
            
            //WaitForSingleObject( m_hOprEvent, dwTimeout );
            
            memset( m_RecvData, 0, MAX_RECV_LEN );
            m_ulRecvDataLen = 0; 

            
        }
        else
        {
            if((bNoCheckBaud) && (lpSendData) )
            {
                free(lpSendData);
            }
        }*/
    }

    
    if( m_dwLastErrorCode == 0 )
    {
        m_dwLastErrorCode = BSL_PHONE_WAIT_INPUT_TIMEOUT;        
    }
    
    return m_bOperationSuccess;
}

BOOL SendCommandData( CMD_TYPE nCmdType, DWORD dwTimeout /* = 1000  */ )
{
    BYTE btSendData[PACHET_HDR_LEN];
    
    memset(&btSendData, 0, PACHET_HDR_LEN);    
    *(short *)&btSendData[PKT_TYPE_POS] = (short)nCmdType;
    
    return SendData( btSendData, PACHET_HDR_LEN , TRUE, dwTimeout );    
}


BOOL SendPacketData( CMD_TYPE nCmdType, 
                                  const int nSendDataLen,
                                  LPBYTE lpPacketData,
                                  UINT uiDataLen,
                                  DWORD dwTimeout /* = 1000  */ )
{
	BOOL bRet = 0;
	UINT i = 0;
    LPBYTE lpSendData = malloc(nSendDataLen);
    if( lpSendData == NULL )
    {
        return FALSE;
    }
    
    //Clear Memory
    memset(lpSendData, 0, nSendDataLen);
    
    //Fill The Packet Type         
    *(short *)&lpSendData[PKT_TYPE_POS]   = (short)nCmdType;
    *(short *)&lpSendData[PKT_LEN_POS]    = (short)uiDataLen ;  
    
    for( i = 0; i < uiDataLen / sizeof( DWORD ); i++ )
    {
        if( m_bBigEndian )
        {
            DWORD dwSoruceValue, dwDestValue;
			
            dwSoruceValue =  *(DWORD *)&lpPacketData[ i * sizeof( DWORD) ];    
            dwDestValue   = 0;
            CONVERT_INT( dwSoruceValue, dwDestValue);
            *(DWORD *)&lpSendData[PKT_DATA_POS + i * sizeof( DWORD) ] = dwDestValue;
        }
        else
        {    
            *(DWORD *)&lpSendData[ PKT_DATA_POS + i * sizeof( DWORD)  ] 
				= *(DWORD *)&lpPacketData[ i * sizeof( DWORD) ];
        }
    }
    
    bRet = SendData( lpSendData, nSendDataLen , TRUE, dwTimeout );
    free(lpSendData);

    return bRet;
}



BOOL CheckBaud7E( DWORD dwTimeout /* = 1000  */)
{
	int nSize = 1;
	BOOL bSuccess = 0;
    //Send Connect Packet to Phone
    char btSendData[ PACHET_HDR_LEN ];
    memset( btSendData, 0x7E, PACHET_HDR_LEN);


		bSuccess = SendData( btSendData, nSize, FALSE, dwTimeout );
		if( m_dwLastErrorCode == BSL_UART_SEND_ERROR)
		{
			//Sleep( 500 );
		}

    return bSuccess;
}


BOOL _CheckBaud(BOOL bRom)
{
    BOOL bRet = FALSE;
    int nTimes = 0;
    int   nMaxTimes = 100000;
	DWORD dwTimeout = bRom ? 10: 10000;
	
	if (bRom)
	{
			m_bCheckCrc = TRUE;
	} 
	else
	{
			m_bCheckCrc = FALSE;
	}

	if (m_bCheckBaudRate)
	{
		return TRUE;
	}

    while( !m_bStopOpr )
    {
        if( nMaxTimes != 0 )
        {
            if( nTimes > nMaxTimes )
            {
                m_bCheckBaudRate = FALSE;
                bRet = FALSE;
                break;
            }
        }
		
        nTimes++;
        
        if(FALSE == m_bCheckBaudRate)
        {
            //m_bCheckBaudRate = TRUE;
        } 		
        
        if( !CheckBaud7E( dwTimeout ) ) // Failed
        {           
            //m_bCheckBaudRate = TRUE;
            continue;
        } 
        
        // Success
        bRet = TRUE;		
        //m_bCheckBaudRate = FALSE;        
		m_bCheckBaudRate = TRUE;    
		ALOGI("Check BaudRate success");    
        break;
    }
	
    
    return bRet;
}

BOOL CheckBaud() 
{
	return _CheckBaud(FALSE);
}

BOOL CheckBaudRom() 
{
	return _CheckBaud(TRUE);
}

BOOL ConnectCMD( DWORD dwTimeout /* = 1000  */)
{
	BOOL bSuccess = SendCommandData( BSL_CMD_CONNECT, dwTimeout  );
	ALOGE( "Connect to Module");
	
	return bSuccess;
}

BOOL _Connect(BOOL bRom) 
{    
	 int nTimeout = 1000;

    if( !_CheckBaud(bRom ) )
    {
        return FALSE;
    }
    
    
    if( !ConnectCMD( nTimeout ) )
    {
        // Boot code in module has a 
        // bug,it possibly make connect
        // failed at first time,so we
        // try once more.
        if( !ConnectCMD( nTimeout ) )
        {
            return FALSE;
        }
    }
    return TRUE;
}


BOOL Connect() 
{
	return _Connect(FALSE);
}

BOOL ConnectRom() 
{
	m_bCheckCrc = TRUE;
	return _Connect(TRUE);
}

DWORD DoCheckSum(LPBYTE pDataBuf,DWORD dwSize)
{
	DWORD dwSum = 0;
	UINT i;
	//////////////////////////////////////////////////////////////////////////
	//make crc and add to the first two byte of data
	//notice: pDataBuf is bigendian, and do CRC not including the first WORD
	WORD wUpdateCrc = crc16(0,pDataBuf+sizeof(WORD),dwSize-sizeof(WORD));
	*pDataBuf = HIBYTE(wUpdateCrc);
	*(pDataBuf+1) = LOBYTE(wUpdateCrc);
	
	
	
	for(i= 0; i< dwSize; i++)
	{
		dwSum += (BYTE)(*(pDataBuf+i));
	}
	
	return dwSum;
}


BOOL StartData( DWORD dwBase,DWORD dwLength , 
							 LPBYTE lpDownLoadData,
							 DWORD dwTimeout /* = 1000  */ )
{
	BYTE szOpr[ MAX_LOG_LEN ] = {0};	
	int nSendDataLen = START_BSL_PKT_LEN;    
    UINT uiDataLen =  2 * sizeof(DWORD) ;
	DWORD dwCheckSum = 0;
    DWORD dwSize = dwLength;
	BYTE* lpPackData;
	BOOL bSuccess;

    if( dwSize % 2 )
    {
        dwSize++;
    }
	
    ALOGE("StartData");
    
	if(m_bNVHasCheckSum)
	{
		uiDataLen += sizeof(DWORD);
		nSendDataLen += sizeof(DWORD);
		dwCheckSum = DoCheckSum(lpDownLoadData,dwLength);
		if( 0 == dwCheckSum )
		{
			ALOGE( "%s( Base:0x%08X, Size:0x%08X, CheckSum:0x%08X)", "Start Data",
				dwBase, dwLength, dwCheckSum);
			return FALSE;
		}
	}	
	
    lpPackData = malloc(uiDataLen);
    if( lpPackData == NULL )
        return FALSE;    
    
    *(DWORD *)&lpPackData[ 0 ] = dwBase;
    *(DWORD *)&lpPackData[ sizeof(DWORD) ] = dwSize;
	
	if(m_bNVHasCheckSum)
	{
		*(DWORD *)&lpPackData[ sizeof(DWORD)*2 ] = dwCheckSum;
	}
	
    m_lpCurrRead = lpDownLoadData;
	
    
    bSuccess = SendPacketData( BSL_CMD_START_DATA,
		nSendDataLen, lpPackData, 
		uiDataLen , dwTimeout );
    free(lpPackData);
    
    
	if(!m_bNVHasCheckSum)
	{
		ALOGE("%s( Base:0x%08X, Size:0x%08X)", "Start Data", dwBase, dwLength );
	}
	else
	{
		ALOGE( szOpr,"%s( Base:0x%08X, Size:0x%08X, CheckSum:0x%08X)", "Start Data",
			dwBase, dwLength, dwCheckSum);
	}
    
    return bSuccess;
}


BOOL MidstData( DWORD dwLength, 
                             DWORD dwTimeout /* = 1000  */ )
{
	BOOL  bState;
	BYTE*  btSendData;
    BOOL  bOddLength = FALSE;
    if( (0x1) == (dwLength & 0x1)  )
    {
        dwLength = dwLength + 1;
        bOddLength = TRUE;
    }
    
    btSendData =  malloc( PACHET_HDR_LEN + dwLength );
    if( btSendData == NULL )
        return FALSE;
	
    
	
    //Clear the memory
    memset(btSendData, 0, PACHET_HDR_LEN + dwLength  );
    
    //Fill The Packet Type         
    *(short *)&btSendData[PKT_TYPE_POS] = BSL_CMD_MIDST_DATA;
    *(short *)&btSendData[PKT_LEN_POS]  = (short)dwLength;
    
    if(TRUE == bOddLength)
    {
        memcpy(&btSendData[PKT_DATA_POS], m_lpCurrRead, dwLength - 1 );
        btSendData[PACHET_HDR_LEN + dwLength - 1] = 0x0;
        m_lpCurrRead += dwLength - 1;    
    }
    else
    {
        memcpy(&btSendData[PKT_DATA_POS], m_lpCurrRead, dwLength  );
        m_lpCurrRead += dwLength;    
    }
    
    bState = SendData( btSendData, dwLength + PACHET_HDR_LEN , TRUE, dwTimeout );    
    
    free(btSendData);
	
    if( m_dwLastErrorCode == BSL_REP_DOWN_DEST_ERROR )
    {
    }
    else
    {
    }
	
    
    return bState;
}

BOOL EndData( DWORD dwTimeout /* = 1000  */ )
{
    BOOL bSuccess = SendCommandData( BSL_CMD_END_DATA, dwTimeout );
    if( !bSuccess &&  m_dwLastErrorCode == BSL_REP_DOWN_DEST_ERROR )
    {
       
    }
    else
    {
        
    }
    
    return bSuccess;
}

BOOL DownLoadBuf(UINT nAddress, BYTE* szID, BYTE* pBuf, int nLen)
{
	DWORD dwLeft;
    DWORD dwMaxLength;
    DWORD dwSize;
	
	if(strcmp(szID,"NV")==0 || 
		strcmp(szID,"NV_REPEAT")==0 )
	{
		m_bNVHasCheckSum = TRUE;
	}
	else
	{
		m_bNVHasCheckSum = FALSE;
	}
	
	if(strcmp(szID,"FDL")==0 )
	{
		dwMaxLength = 0x200;
	}
	else
	{
		dwMaxLength = 0x700;
	}
		
    if(!StartData( nAddress,  nLen,  (LPBYTE)pBuf, 1000 ) )
    {
        return FALSE;
    }

    dwLeft = nLen;    
    dwSize = dwMaxLength;
	
    while( dwLeft > 0 && !m_bStopOpr )
    {
        if(dwLeft > dwMaxLength )
        {
            dwSize = dwMaxLength ;                
        }
        else
        {
            dwSize = dwLeft;
        }
        
        if( !MidstData( dwSize, 1000) )
        {
            return FALSE;
        }
        dwLeft -= dwSize;
        //PostMessageToUplevel( BM_DOWNLOAD_PROCESS, (WPARAM)m_dwOprCookie, (LPARAM)pBMFileInfo->dwCodeSize - dwLeft );   
        down_percent(szID, StepWorking, nLen-dwLeft,nLen);
    }
    if( m_bStopOpr )
    {
        return FALSE;
    }
    if( !EndData( 1000 ) )
        return FALSE;
    return TRUE;
}

BOOL Download_m7281(UINT nAddress, long pFileInfo) 
{
    //PostMessageToUplevel( BM_ERASE_FLASH, (WPARAM)m_dwOprCookie, (LPARAM)0 );
	DWORD dwLeft;
    DWORD dwMaxLength;
    DWORD dwSize;
	DWORD dwFileLen;
	BYTE* pFileBuf = NULL;
	FILE* hFile = NULL;

	FILE_T* pFile = (FILE_T*)pFileInfo;

	if(strcmp(pFile->szFileID,"nv")==0 || 
		strcmp(pFile->szFileID,"nv_repeat")==0 )
	{
		m_bNVHasCheckSum = TRUE;
	}
	else
	{
		m_bNVHasCheckSum = FALSE;
	}

	if(strcmp(pFile->szFileID,"fdl")==0 )
	{
		dwMaxLength = 0x200;
	}
	else
	{
		dwMaxLength = 0x800;
	}
	
	hFile = fopen(pFile->szFileName, "r");
	if(INVALID_HANDLE_VALUE ==  hFile)
	{
	    ALOGE("Download %s file open file", pFile->szFileName);
		return FALSE;
	}
	fseek(hFile, 0, SEEK_END);
	dwFileLen = ftell(hFile);
	fseek(hFile, 0, SEEK_SET);
	pFileBuf = malloc(dwFileLen);
	if (pFileBuf == NULL)
	{
		free(pFileBuf);
		fclose(hFile);
		return FALSE;
	}
	if (dwFileLen != fread(pFileBuf, 1, dwFileLen, hFile))
	{
		free(pFileBuf);
		fclose(hFile);
		return FALSE;
	}
	fclose(hFile);	

    if(!StartData( nAddress,  dwFileLen,  (LPBYTE)pFileBuf, 1000 ) )
    {
		free(pFileBuf);
        return FALSE;
    }
    
    //PostMessageToUplevel( BM_DOWNLOAD, (WPARAM)m_dwOprCookie, (LPARAM)pBMFileInfo->dwCodeSize );
	
    dwLeft = pFile->nFileSize;    
    dwSize = dwMaxLength;
	
    while( dwLeft > 0 && !m_bStopOpr )
    {
        if(dwLeft > dwMaxLength )
        {
            dwSize = dwMaxLength ;                
        }
        else
        {
            dwSize = dwLeft;
        }
        
        if( !MidstData( dwSize, 1000) )
        {
			free(pFileBuf);
            return FALSE;
        }
        dwLeft -= dwSize;
        //PostMessageToUplevel( BM_DOWNLOAD_PROCESS, (WPARAM)m_dwOprCookie, (LPARAM)pBMFileInfo->dwCodeSize - dwLeft );   
        down_percent(pFile->szFileID, StepWorking, dwFileLen-dwLeft,dwFileLen);
    }
    if( m_bStopOpr )
    {
		free(pFileBuf);
        return FALSE;
    }
    if( !EndData( 10000 ) )
	{
		free(pFileBuf);
        return FALSE;
	}
	free(pFileBuf);
	ALOGE("Download pFile->szFileID=%s ok", pFile->szFileID );
    return TRUE;
}

BOOL Download_m1190(UINT nAddress, long pFileInfo) 
{
    //PostMessageToUplevel( BM_ERASE_FLASH, (WPARAM)m_dwOprCookie, (LPARAM)0 );
	DWORD dwLeft;
    DWORD dwMaxLength;
    DWORD dwSize;
	DWORD dwFileLen;
	BYTE* pFileBuf = NULL;
	FILE* hFile = NULL;

	FILE_T* pFile = (FILE_T*)pFileInfo;

	if(strcmp(pFile->szFileID,"nv")==0 || 
		strcmp(pFile->szFileID,"nv_repeat")==0 )
	{
		m_bNVHasCheckSum = TRUE;
	}
	else
	{
		m_bNVHasCheckSum = FALSE;
	}

	if(strcmp(pFile->szFileID,"fdl")==0 )
	{
		dwMaxLength = 0x200;
	}
	else
	{
		dwMaxLength = 0x800;
	}
	
	hFile = fopen(pFile->szFileName, "r");
	if(INVALID_HANDLE_VALUE ==  hFile)
	{
	    ALOGE("Download %s file open file", pFile->szFileName);
		return FALSE;
	}
	fseek(hFile, 0, SEEK_END);
	dwFileLen = ftell(hFile);
	fseek(hFile, 0, SEEK_SET);
	pFileBuf = malloc(dwFileLen);
	if (pFileBuf == NULL)
	{
		free(pFileBuf);
		fclose(hFile);
		return FALSE;
	}
	if (dwFileLen != fread(pFileBuf, 1, dwFileLen, hFile))
	{
		free(pFileBuf);
		fclose(hFile);
		return FALSE;
	}
	fclose(hFile);	

    if(!StartData( nAddress,  dwFileLen,  (LPBYTE)pFileBuf, 1000 ) )
    {
		free(pFileBuf);
        return FALSE;
    }
    
    //PostMessageToUplevel( BM_DOWNLOAD, (WPARAM)m_dwOprCookie, (LPARAM)pBMFileInfo->dwCodeSize );
	
    dwLeft = pFile->nFileSize;    
    dwSize = dwMaxLength;
	
    while( dwLeft > 0 && !m_bStopOpr )
    {
        if(dwLeft > dwMaxLength )
        {
            dwSize = dwMaxLength ;                
        }
        else
        {
            dwSize = dwLeft;
        }
        
        if( !MidstData( dwSize, 1000) )
        {
			free(pFileBuf);
            return FALSE;
        }
        dwLeft -= dwSize;
        //PostMessageToUplevel( BM_DOWNLOAD_PROCESS, (WPARAM)m_dwOprCookie, (LPARAM)pBMFileInfo->dwCodeSize - dwLeft );   
        down_percent(pFile->szFileID, StepWorking, dwFileLen-dwLeft,dwFileLen);
    }
    if( m_bStopOpr )
    {
		free(pFileBuf);
        return FALSE;
    }
    if( !EndData( 1000 ) )
	{
		free(pFileBuf);
        return FALSE;
	}
	free(pFileBuf);
	ALOGE("Download pFile->szFileID=%s ok", pFile->szFileID );
    return TRUE;
}


BOOL Excute( )
{

    BOOL bSuccess = SendCommandData( BSL_CMD_EXEC_DATA , 1000 );
    ALOGE("Excute downloaded file bSuccess = %d", bSuccess);
	
	m_bCheckBaudRate = FALSE;

    return bSuccess;
}


BOOL ChangeBaud()
{
    DWORD dwBaud = DOWNLOAD_BAUD;
    BOOL bOK = TRUE;
	BOOL bSuccess;
	//_TCHAR szOpr[ MAX_LOG_LEN ];
    UINT uiDataLen = sizeof( DWORD );
	BYTE lpPackData[4] = {0};
    
	//m_bCheckCrc = TRUE;
	
    *(DWORD *)&lpPackData[ 0 ] = DOWNLOAD_BAUD;    
    
    bSuccess = SendPacketData( BSL_SET_BAUDRATE, uiDataLen  + PACHET_HDR_LEN , lpPackData, uiDataLen, 1000  );
	
    
    ALOGE("FDL:Change Baudrate( %d )", DOWNLOAD_BAUD );
    //LogOpr( szOpr, bSuccess );
    
    if( bSuccess )
    {
        bSuccess = scom_change_baud(DOWNLOAD_BAUD);
        //usleep( 10000 );
		ALOGD("scom_change_baud : %s\n", bSuccess ? "SUCCESS" : "FAILED" );
        sleep( 10 );
    }
    
    //_stprintf( szOpr, _T("BMPlatform:Change Baudrate( %d )"), dwBaud );
    //LogOpr( szOpr, bSuccess );            
    
    return bSuccess;
}

BYTE* GetFlashName()
{
	return m_szMCP;
}
BOOL ReadMCPType()
{
	//_TCHAR szOpr[ MAX_LOG_LEN ];

    BOOL bSuccess = SendCommandData( BSL_CMD_READ_MCP_TYPE, 1000 );

	ALOGE("Read MCP Info: %s ", m_szMCP );
    //LogOpr( _T("ReadMCPType"),bSuccess );

    return bSuccess; 
}

BOOL SendFDLVersion()
{
	int nVer = 2;
	BOOL bSuccess;
    UINT uiDataLen =  sizeof(UINT);
    BYTE lpPackData[4]={0};
    //_TCHAR szOpr[ MAX_LOG_LEN ];
	
    *(UINT *)&lpPackData[ 0 ] = nVer;    
    bSuccess = SendPacketData( BSL_CMD_FDL_VER, PACHET_HDR_LEN +sizeof(UINT), 
        lpPackData, uiDataLen , 1000  );        
   
    ALOGE("%s :0x%08X ", "Send FDL Version", nVer );
    //LogOpr( szOpr, bSuccess );
    
    if(  m_dwLastErrorCode == BSL_REP_VER_ERROR )
    {
        //Log( _T("End Data:Doownload error in previous command") );
    }
	
    return bSuccess; 
}

BOOL ReadSectorSize()
{
    BOOL bSuccess = SendCommandData( BSL_CMD_READ_SECTOR_SIZE, 1000 );
    ALOGE("Read sector size bSuccess =%d",bSuccess );
    return bSuccess;
}

BOOL DownloadFDL2(UINT nAddress, long pFileInfo)
{
	BOOL bRet = 0;
	char* szStep = "FDL2";
	
	down_percent(szStep, StepStart, 0,0);

	bRet = Download_m7281(nAddress, (long)pFileInfo);
	if (bRet == 0)
	{
		down_percent("Download", StepFail, 0,0);
		return FALSE;
	}
	
	bRet = Excute();
	if (bRet == 0)
	{
		down_percent("Excute", StepFail, 0,0);
		return FALSE;
	}
			
	return bRet;
}

BOOL DownloadFDL_m7281(UINT nAddress, long pFileInfo)
{
	BOOL bRet = 0;
	char* szStep = "FDL";

	down_percent(szStep, StepStart, 0,0);
	bRet = CheckBaudRom();
	if (bRet == 0)
	{
		down_percent("CheckBaudRom", StepFail, 0,0);
		return FALSE;
	}

	bRet = ConnectRom();
	if (bRet == 0)
	{
		down_percent("ConnectRom", StepFail, 0,0);
		return FALSE;
	}

	bRet = Download_m7281(nAddress, (long)pFileInfo);
	if (bRet == 0)
	{
		down_percent("Download", StepFail, 0,0);
		return FALSE;
	}

	bRet = Excute();
	if (bRet == 0)
	{
		down_percent("Excute", StepFail, 0,0);
		return FALSE;
	}
/*
	bRet = CheckBaud();
	if (bRet == 0)
	{
		down_percent("CheckBaud", StepFail, 0,0);
		return FALSE;
	}
*/
	bRet = Connect();
	if (bRet == 0)
	{
		down_percent("Connect", StepFail, 0,0);
		return FALSE;
	}

	
	bRet = ChangeBaud();
	if (bRet == 0)
	{
		down_percent("ChangeBaud", StepFail, 0,0);
		return FALSE;
	}

	/*bRet = ReadMCPType();
	if (bRet == 0)
	{
		down_percent("ReadMCPType", StepFail, 0,0);
		return FALSE;
	}
	*/

	/*bRet = SendFDLVersion();
	if (bRet == 0)
	{
		down_percent("SendFDLVersion", StepFail, 0,0);
		return FALSE;
	}

	bRet = ReadSectorSize();
	if (bRet == 0)
	{
		down_percent("ReadSectorSize", StepFail, 0,0);
		return FALSE;
	}*/

	return bRet;
}

BOOL DownloadFDL_m1190(UINT nAddress, long pFileInfo)
{
	BOOL bRet = 0;
	char* szStep = "FDL";

	down_percent(szStep, StepStart, 0,0);
	bRet = CheckBaudRom();
	if (bRet == 0)
	{
		down_percent("CheckBaudRom", StepFail, 0,0);
		return FALSE;
	}

	bRet = ConnectRom();
	if (bRet == 0)
	{
		down_percent("ConnectRom", StepFail, 0,0);
		return FALSE;
	}

	bRet = Download_m1190(nAddress, (long)pFileInfo);
	if (bRet == 0)
	{
		down_percent("Download", StepFail, 0,0);
		return FALSE;
	}

	bRet = Excute();
	if (bRet == 0)
	{
		down_percent("Excute", StepFail, 0,0);
		return FALSE;
	}
/*
	bRet = CheckBaud();
	if (bRet == 0)
	{
		down_percent("CheckBaud", StepFail, 0,0);
		return FALSE;
	}
*/
	bRet = Connect();
	if (bRet == 0)
	{
		down_percent("Connect", StepFail, 0,0);
		return FALSE;
	}

	/*
	bRet = ChangeBaud();
	if (bRet == 0)
	{
		down_percent("ChangeBaud", StepFail, 0,0);
		return FALSE;
	}

	bRet = ReadMCPType();
	if (bRet == 0)
	{
		down_percent("ReadMCPType", StepFail, 0,0);
		return FALSE;
	}
	*/

	bRet = SendFDLVersion();
	if (bRet == 0)
	{
		down_percent("SendFDLVersion", StepFail, 0,0);
		return FALSE;
	}

	bRet = ReadSectorSize();
	if (bRet == 0)
	{
		down_percent("ReadSectorSize", StepFail, 0,0);
		return FALSE;
	}

	return bRet;
}

BOOL DownloadFile(UINT nAddress, long pFileInfo)
{
	BOOL bRet = 1;

	bRet = mDownloadCallback.onDownload(nAddress, (long)pFileInfo);
	if (bRet == 0)
	{
		down_percent("Download", StepFail, 0,0);
		return FALSE;
	}

	return bRet;
}

BOOL EraseFlash( DWORD dwBase,DWORD dwLength)
{
	BOOL bSuccess;
    DWORD dwSize = dwLength;
	//_TCHAR szOpr[ MAX_LOG_LEN ];    
    UINT uiDataLen =  2 * sizeof(DWORD) ;
    BYTE lpPackData[8];

    
    *(DWORD *)&lpPackData[ 0 ] = dwBase;
    *(DWORD *)&lpPackData[ sizeof(DWORD) ] = dwSize;
	
	if( dwSize % 2 )
    {
        dwSize++;
    }
    bSuccess = SendPacketData( BSL_ERASE_FLASH,ERASE_FLASH_PKT_LEN, lpPackData, uiDataLen , 5000 );
    
    
    //_stprintf( szOpr,_T("%s( Base:0x%08X, Size:0x%08X)"), _T("Erase Flash"), dwBase, dwLength );
    //LogOpr( szOpr, bSuccess );
    
    return bSuccess;    
}

BOOL FormatFlash(UINT nAddress, long pFileInfo)
{
	FILE_T* pFile = (FILE_T*)pFileInfo;
	BOOL bRet = EraseFlash(nAddress, pFile->nFileSize);
	
	return bRet;
}


BOOL ReadPartitionFlash( DWORD dwBase,DWORD dwLength,DWORD dwOffset)
{
	BOOL bSuccess;
	BOOL bRetried = FALSE;
	//_TCHAR szOpr[ MAX_LOG_LEN ];
    UINT uiDataLen =  START_BSL_PKT_LEN - PACHET_HDR_LEN + sizeof( DWORD );
    BYTE* lpPackData = malloc(uiDataLen);
    if( lpPackData == NULL )
        return FALSE; 
    
    m_uiReadOffset = 0;
    
ReadPartitionFlash_Retry:
    
    *(DWORD *)&lpPackData[ 0 ] = dwBase;
    *(DWORD *)&lpPackData[ sizeof(DWORD) ] = dwLength;
    *(DWORD *)&lpPackData[ sizeof( DWORD ) * 2 ] = dwOffset;
    m_dwLastPktSize = dwLength;
    
    m_lpCurrRead = NULL;
    
    bSuccess = SendPacketData( BSL_CMD_READ_FLASH, START_BSL_PKT_LEN + sizeof( DWORD ), 
        lpPackData, uiDataLen , 1000  );
    if( !bSuccess && !bRetried)
    {
        bRetried = TRUE;
        ALOGE( "retry ReadPartitionFlash.");
        goto ReadPartitionFlash_Retry;
    }
        
        
    free(lpPackData);
    
    
    //ALOGE("%s( Base:0x%08X, Size:0x%08X, Offset:0x%08X )", "Read Flash", dwBase, dwLength,dwOffset );
    //LogOpr( szOpr, bSuccess );
    
    return bSuccess;
}


BOOL AllocRecvBuffer( DWORD dwSize )
{
    if( m_lpReceiveBuffer != NULL )
    {
        if( m_dwBufferSize == dwSize )
        {
            memset( m_lpReceiveBuffer, 0, m_dwBufferSize );
            m_dwReceiveLen = 0;
        }
        else
        {
            free(m_lpReceiveBuffer);
            m_lpReceiveBuffer = NULL;
            m_dwReceiveLen = 0;
            m_dwBufferSize = 0;            
        }
    }
    if( m_lpReceiveBuffer == NULL )
    {
        m_lpReceiveBuffer = malloc(dwSize);
        if( m_lpReceiveBuffer == NULL )
            return FALSE;
        m_dwReceiveLen = 0;
        m_dwBufferSize = dwSize;
    }
        
    return TRUE;
}

LPBYTE GetRecvBuffer()
{
    return m_lpReceiveBuffer;
}

DWORD GetRecvBufferSize()
{
    return m_dwReceiveLen;
}

void FreeRecvBuffer()
{
    if( m_lpReceiveBuffer != NULL )
    {
        free(m_lpReceiveBuffer);
        m_lpReceiveBuffer = NULL;
        m_dwReceiveLen = 0;    
        m_dwBufferSize = 0;
    }	
}


BOOL ReadFlash(UINT nAddress,long pFileInfo) 
{
	
   //BMFileInfo* pBMFileInfo = (BMFileInfo*)pFileInfo;
   
	FILE_T* pFile = (FILE_T*)pFileInfo;
	UINT nReadSize = pFile->nFileSize;
    // Read NV_LENGTH byte from module
    

    DWORD dwBase = nAddress;
    DWORD dwLeft = nReadSize;
    DWORD dwMaxLength = 0x100;    
    DWORD dwSize = dwMaxLength; 
    DWORD dwOffset = 0;

	AllocRecvBuffer( nReadSize );
       while(dwLeft > 0 && !m_bStopOpr )
       {
            if(dwLeft > dwMaxLength )
            {
                dwSize = dwMaxLength ;                
            }
            else
            {
                dwSize = dwLeft;
            }
			ALOGE("ReadFlash dwOffset= %X",dwOffset);
            if( !ReadPartitionFlash( dwBase,dwSize,dwOffset ) )
            {
                FreeRecvBuffer();
                return FALSE;
            }
		
            dwOffset += dwSize;
            dwLeft -= dwSize;
            //PostMessageToUplevel( BM_READ_FLASH_PROCESS, (WPARAM)m_dwOprCookie, (LPARAM)pBMFileInfo->dwOprSize - dwLeft );        
	   }
	
    if( m_bStopOpr )
        return FALSE;
    return TRUE;
}

BOOL DownloadNV_m7281(UINT nAddress,long pFileInfo)
{
	FILE_T* pNVInfo = (FILE_T*)pFileInfo;
	BOOL bRet = FALSE;
	BYTE* pReadNV = NULL;
	UINT nReadNVLen = 0;
	BYTE* pFileNV = NULL;
	UINT nFileNVLen = pNVInfo->nFileSize;
	
	{
		FILE* pFile = fopen(pNVInfo->szFileName, "r");
		if (NULL == pFile)
		{
			return FALSE;
		}

		pFileNV = malloc(nFileNVLen);
		if (pFileNV == NULL)
		{
			fclose(pFile);
			return FALSE;
		}
		ALOGE("DownloadNV nFileNVLen=%X",nFileNVLen);
		if ( nFileNVLen != fread(pFileNV, 1, nFileNVLen, pFile))
		{
			free(pFileNV);
			fclose(pFile);
			return FALSE;
		}

		fclose(pFile);
	}

	//pNVInfo->nFileSize = 0x10000;
	pNVInfo->nFileSize = 0x40000;
	if (FALSE == ReadFlash(nAddress,pFileInfo) )
	{
		ALOGE("DownloadNV ReadFlash error");
		free(pFileNV);
		return FALSE;
	}

	pReadNV = GetRecvBuffer();
	nReadNVLen = GetRecvBufferSize();
	ALOGE("nReadNVLen=%d", nReadNVLen);
	/*
	if (1)
	{
		FILE* pFile = _tfopen(_T("F:\\test\\nv_read.bin"), _T("wb+"));
		fwrite(pReadNV, 1, nReadNVLen, pFile);
		fclose(pFile);
	}*/


	if (1)
	{		
		DWORD dwErrorRCID = GSMCaliPreserve( pFileNV, nFileNVLen, pReadNV, nReadNVLen, FALSE, FALSE);
		if(  dwErrorRCID !=0  )
		{
			//TCHAR* pError = GetErrorDesc( dwErrorRCID );
			//LogOpr(_T("BackupCal"), FALSE);
			//Log(pError);

			free(pFileNV);
			return FALSE;
		}
/*
		if (1)
		{
			FILE* pFile = _tfopen(_T("F:\\test\\nv_new_cal.bin"), _T("wb+"));
			fwrite(pFileNV, 1, nFileNVLen, pFile);
			fclose(pFile);
		}*/
	}

	if (1)
	{
		int nFailedIMEIIndex = 0;
		int nIMEI[4] = {5, 0x179,0x186,0x1e4};
		DWORD dwErrorRCID = XPreserveIMEIs( nIMEI, 4,  pFileNV, nFileNVLen, pReadNV, nReadNVLen, &nFailedIMEIIndex, FALSE, FALSE);
		if(  dwErrorRCID !=0  )
		{
			//TCHAR* pError = GetErrorDesc( dwErrorRCID );
			//LogOpr(_T("BackupIMEI"), FALSE);
			//Log(pError);
			
			free(pFileNV);
			return FALSE;
		}	
/*
		if (1)
		{
			FILE* pFile = _tfopen(_T("F:\\test\\nv_new_cal_imei.bin"), _T("wb+"));
			fwrite(pFileNV, 1, nFileNVLen, pFile);
			fclose(pFile);
		}*/
	}

	if (1)
	{
		int i = 0;
		int nIDs[4] = {0xD, 0x191,0x199,0x12D};
		for (i = 0; i < 4; i++)
		{
			DWORD dwErrorRCID = XPreserveNVItem( (WORD)(nIDs[i]), pFileNV, nFileNVLen, pReadNV, nReadNVLen,FALSE, FALSE);
			if(  dwErrorRCID !=0  )
			{
				//TCHAR* pError = GetErrorDesc( dwErrorRCID );
				//LogOpr(_T("BackupNVItem"), FALSE);
				//Log(pError);
				
				free(pFileNV);
				return FALSE;
			}  
		}	
		
		/*
		if (1)
		{
			FILE* pFile = _tfopen(_T("F:\\test\\nv_new_cal_imei_all.bin"), _T("wb+"));
			fwrite(pFileNV, 1, nFileNVLen, pFile);
			fclose(pFile);
		}*/
	}

	bRet = DownLoadBuf(nAddress, "NV", pFileNV, nFileNVLen);
	if (bRet == 0)
	{
		free(pFileNV);
		return FALSE;
	}
		
	if (FALSE == ReadFlash(nAddress,pFileInfo) )
	{
		free(pFileNV);
		return FALSE;
	}
	pReadNV = GetRecvBuffer();
	nReadNVLen = GetRecvBufferSize();
	if (memcmp(pFileNV, pReadNV, nFileNVLen) != 0)
	{
		free(pFileNV);
		return FALSE;
	}
    
	return bRet;
}

BOOL DownloadNV_m1190(UINT nAddress,long pFileInfo)
{
	FILE_T* pNVInfo = (FILE_T*)pFileInfo;
	BOOL bRet = FALSE;
	BYTE* pReadNV = NULL;
	UINT nReadNVLen = 0;
	BYTE* pFileNV = NULL;
	UINT nFileNVLen = pNVInfo->nFileSize;
	
	{
		FILE* pFile = fopen(pNVInfo->szFileName, "r");
		if (NULL == pFile)
		{
			return FALSE;
		}

		pFileNV = malloc(nFileNVLen);
		if (pFileNV == NULL)
		{
			fclose(pFile);
			return FALSE;
		}
		ALOGE("DownloadNV nFileNVLen=%X",nFileNVLen);
		if ( nFileNVLen != fread(pFileNV, 1, nFileNVLen, pFile))
		{
			free(pFileNV);
			fclose(pFile);
			return FALSE;
		}

		fclose(pFile);
	}

	//pNVInfo->nFileSize = 0x10000;
	pNVInfo->nFileSize = 0x4100;
	if (FALSE == ReadFlash(nAddress,pFileInfo) )
	{
		ALOGE("DownloadNV ReadFlash error");
		free(pFileNV);
		return FALSE;
	}

	pReadNV = GetRecvBuffer();
	nReadNVLen = GetRecvBufferSize();
	ALOGE("nReadNVLen=%d", nReadNVLen);
	/*
	if (1)
	{
		FILE* pFile = _tfopen(_T("F:\\test\\nv_read.bin"), _T("wb+"));
		fwrite(pReadNV, 1, nReadNVLen, pFile);
		fclose(pFile);
	}*/


	if (1)
	{		
		DWORD dwErrorRCID = GSMCaliPreserve( pFileNV, nFileNVLen, pReadNV, nReadNVLen, FALSE, FALSE);
		if(  dwErrorRCID !=0  )
		{
			//TCHAR* pError = GetErrorDesc( dwErrorRCID );
			//LogOpr(_T("BackupCal"), FALSE);
			//Log(pError);

			free(pFileNV);
			return FALSE;
		}
/*
		if (1)
		{
			FILE* pFile = _tfopen(_T("F:\\test\\nv_new_cal.bin"), _T("wb+"));
			fwrite(pFileNV, 1, nFileNVLen, pFile);
			fclose(pFile);
		}*/
	}

	if (1)
	{
		int nFailedIMEIIndex = 0;
		int nIMEI[4] = {5, 0x179,0x186,0x1e4};
		DWORD dwErrorRCID = XPreserveIMEIs( nIMEI, 4,  pFileNV, nFileNVLen, pReadNV, nReadNVLen, &nFailedIMEIIndex, FALSE, FALSE);
		if(  dwErrorRCID !=0  )
		{
			//TCHAR* pError = GetErrorDesc( dwErrorRCID );
			//LogOpr(_T("BackupIMEI"), FALSE);
			//Log(pError);
			
			free(pFileNV);
			return FALSE;
		}	
/*
		if (1)
		{
			FILE* pFile = _tfopen(_T("F:\\test\\nv_new_cal_imei.bin"), _T("wb+"));
			fwrite(pFileNV, 1, nFileNVLen, pFile);
			fclose(pFile);
		}*/
	}

	if (1)
	{
		int i = 0;
		int nIDs[4] = {0xD, 0x191,0x199,0x19A};
		for (i = 0; i < 4; i++)
		{
			DWORD dwErrorRCID = XPreserveNVItem( (WORD)(nIDs[i]), pFileNV, nFileNVLen, pReadNV, nReadNVLen,FALSE, FALSE);
			if(  dwErrorRCID !=0  )
			{
				//TCHAR* pError = GetErrorDesc( dwErrorRCID );
				//LogOpr(_T("BackupNVItem"), FALSE);
				//Log(pError);
				
				free(pFileNV);
				return FALSE;
			}  
		}	
		
		/*
		if (1)
		{
			FILE* pFile = _tfopen(_T("F:\\test\\nv_new_cal_imei_all.bin"), _T("wb+"));
			fwrite(pFileNV, 1, nFileNVLen, pFile);
			fclose(pFile);
		}*/
	}

	bRet = DownLoadBuf(nAddress, "NV", pFileNV, nFileNVLen);
	if (bRet == 0)
	{
		free(pFileNV);
		return FALSE;
	}
		
	if (FALSE == ReadFlash(nAddress,pFileInfo) )
	{
		free(pFileNV);
		return FALSE;
	}
	pReadNV = GetRecvBuffer();
	nReadNVLen = GetRecvBufferSize();
	if (memcmp(pFileNV, pReadNV, nFileNVLen) != 0)
	{
		free(pFileNV);
		return FALSE;
	}
    
	return bRet;
}

BOOL DownloadNV_m0282(UINT nAddress,long pFileInfo)
{
	FILE_T* pNVInfo = (FILE_T*)pFileInfo;
	BOOL bRet = FALSE;
	BYTE* pReadNV = NULL;
	UINT nReadNVLen = 0;
	BYTE* pFileNV = NULL;
	UINT nFileNVLen = pNVInfo->nFileSize;
	
	{
		FILE* pFile = fopen(pNVInfo->szFileName, "r");
		if (NULL == pFile)
		{
			return FALSE;
		}

		pFileNV = malloc(nFileNVLen);
		if (pFileNV == NULL)
		{
			fclose(pFile);
			return FALSE;
		}
		ALOGE("DownloadNV nFileNVLen=%X",nFileNVLen);
		if ( nFileNVLen != fread(pFileNV, 1, nFileNVLen, pFile))
		{
			free(pFileNV);
			fclose(pFile);
			return FALSE;
		}

		fclose(pFile);
	}

	pNVInfo->nFileSize = 0x6000;
	//pNVInfo->nFileSize = 0x4100;
	if (FALSE == ReadFlash(nAddress,pFileInfo) )
	{
		ALOGE("DownloadNV ReadFlash error");
		free(pFileNV);
		return FALSE;
	}

	pReadNV = GetRecvBuffer();
	nReadNVLen = GetRecvBufferSize();
	ALOGE("nReadNVLen=%d", nReadNVLen);
	/*
	if (1)
	{
		FILE* pFile = _tfopen(_T("F:\\test\\nv_read.bin"), _T("wb+"));
		fwrite(pReadNV, 1, nReadNVLen, pFile);
		fclose(pFile);
	}*/


	if (1)
	{		
		DWORD dwErrorRCID = GSMCaliPreserve( pFileNV, nFileNVLen, pReadNV, nReadNVLen, FALSE, FALSE);
		if(  dwErrorRCID !=0  )
		{
			//TCHAR* pError = GetErrorDesc( dwErrorRCID );
			//LogOpr(_T("BackupCal"), FALSE);
			//Log(pError);

			free(pFileNV);
			return FALSE;
		}
/*
		if (1)
		{
			FILE* pFile = _tfopen(_T("F:\\test\\nv_new_cal.bin"), _T("wb+"));
			fwrite(pFileNV, 1, nFileNVLen, pFile);
			fclose(pFile);
		}*/
	}

	if (1)
	{
		int nFailedIMEIIndex = 0;
		int nIMEI[4] = {5, 0x179,0x186,0x1e4};
		DWORD dwErrorRCID = XPreserveIMEIs( nIMEI, 4,  pFileNV, nFileNVLen, pReadNV, nReadNVLen, &nFailedIMEIIndex, FALSE, FALSE);
		if(  dwErrorRCID !=0  )
		{
			//TCHAR* pError = GetErrorDesc( dwErrorRCID );
			//LogOpr(_T("BackupIMEI"), FALSE);
			//Log(pError);
			
			free(pFileNV);
			return FALSE;
		}	
/*
		if (1)
		{
			FILE* pFile = _tfopen(_T("F:\\test\\nv_new_cal_imei.bin"), _T("wb+"));
			fwrite(pFileNV, 1, nFileNVLen, pFile);
			fclose(pFile);
		}*/
	}

	if (1)
	{
		int i = 0;
		int nIDs[4] = {0xD, 0x191,0x199,0x19A};
		for (i = 0; i < 4; i++)
		{
			DWORD dwErrorRCID = XPreserveNVItem( (WORD)(nIDs[i]), pFileNV, nFileNVLen, pReadNV, nReadNVLen,FALSE, TRUE);
			if(  dwErrorRCID !=0  )
			{
				//TCHAR* pError = GetErrorDesc( dwErrorRCID );
				//LogOpr(_T("BackupNVItem"), FALSE);
				//Log(pError);
				
				free(pFileNV);
				return FALSE;
			}  
		}	
		
		/*
		if (1)
		{
			FILE* pFile = _tfopen(_T("F:\\test\\nv_new_cal_imei_all.bin"), _T("wb+"));
			fwrite(pFileNV, 1, nFileNVLen, pFile);
			fclose(pFile);
		}*/
	}

	bRet = DownLoadBuf(nAddress, "NV", pFileNV, nFileNVLen);
	if (bRet == 0)
	{
		free(pFileNV);
		return FALSE;
	}
		
	if (FALSE == ReadFlash(nAddress,pFileInfo) )
	{
		free(pFileNV);
		return FALSE;
	}
	pReadNV = GetRecvBuffer();
	nReadNVLen = GetRecvBufferSize();
	if (memcmp(pFileNV + 2, pReadNV + 2, nFileNVLen - 2) != 0)
	{
		free(pFileNV);
		return FALSE;
	}
    
	return bRet;
}

unsigned short SwapWord( unsigned short src )
{
	return MAKEWORD( HIBYTE(src), LOBYTE(src) );
}

unsigned long SwapDword( unsigned long src )
{
	return MAKELONG( SwapWord( HIWORD(src) ),
		             SwapWord( LOWORD(src) ) );
}

LPBYTE MakeMasterImageHeader(DWORD dwPSSize,DWORD *pdwHdrSize, int page_type )
{

	DWORD		dwSectsPerBlock = 0;
	DWORD		dwHeadSize = 0;
	DWORD		dwBootSize= 0;
	BOOT_PARAM * pBoot = NULL;
	OS_INFO    * pOS= NULL;

	BOOT_PARAM * pBootBak= NULL;
	OS_INFO    * pOSBak= NULL;


	LPBYTE pHeadBuf = NULL;

	dwSectsPerBlock = (SMALL_PAGE == page_type) ? 32 : 256;
	dwBootSize = sizeof(BOOT_PARAM) + sizeof( OS_INFO );

	dwHeadSize = dwSectsPerBlock * SECTOR_SIZE;

	pHeadBuf = malloc(dwHeadSize);
	if(pHeadBuf == NULL)
		return NULL;
	memset(pHeadBuf,0xFF,dwHeadSize);

	//init boot param	
	pBoot = (BOOT_PARAM *)pHeadBuf;
	memset(pBoot,0,sizeof(BOOT_PARAM));
	memcpy( pBoot->Magic, MAGIC, sizeof(pBoot->Magic) );
	pBoot->Size = SwapWord((WORD)sizeof( BOOT_PARAM ));
	pBoot->TotalSize = SwapWord((WORD)dwBootSize);
	time(&pBoot->TimeStamp);
	pBoot->TimeStamp = SwapDword( pBoot->TimeStamp );
	pBoot->TraceOn   = ( BYTE )1;
	pBoot->Reserved  = ( BYTE )0;
	pBoot->CurrentOS = ( BYTE )0;
	pBoot->NumOfOS   = ( BYTE )1;
	pBoot->SizeOfOSInfo =  SwapWord((WORD)sizeof( OS_INFO ));
	pBoot->OSOffset  = SwapWord((WORD)sizeof( BOOT_PARAM ));

	//init OS info
	pOS = (OS_INFO*)(((BYTE *)pHeadBuf) + sizeof(BOOT_PARAM));
	memset(pOS,0,sizeof(OS_INFO));
	pOS->Offset =  SwapWord((WORD)dwSectsPerBlock);
	pOS->Size =  SwapWord((WORD)(( dwPSSize + SECTOR_SIZE - 1 ) / SECTOR_SIZE ));

	pBootBak = (BOOT_PARAM*)(pHeadBuf + dwHeadSize/2);
	pOSBak = (OS_INFO*)( ((BYTE*)(pBootBak)) + sizeof(BOOT_PARAM));
	memcpy(pBootBak,pBoot,sizeof(BOOT_PARAM));
	memcpy(pOSBak,pOS,sizeof(OS_INFO));

	*pdwHdrSize = dwHeadSize;

	return pHeadBuf;
	
}

BOOL DownloadKernel(UINT nAddress, long pFileInfo)
{
	FILE_T* pKernelInfo = (FILE_T*)pFileInfo;
	UINT  nFileLen = pKernelInfo->nFileSize;
	UINT  dwHdrSize = 0;
	DWORD dwImgSize= 0;
        BOOL bRet= 0;
        
	LPBYTE pImg = NULL; 
	
	BYTE *pHead = MakeMasterImageHeader(nFileLen,&dwHdrSize, 0 );
	
	if(pHead == NULL)
		return FALSE;	
	
	dwImgSize= dwHdrSize + (((nFileLen + SECTOR_SIZE - 1 ) / SECTOR_SIZE) * SECTOR_SIZE);
	
	pImg = malloc(dwImgSize);
	if(pImg == NULL)
	{
		free(pHead);	
		return FALSE;

	}	
	memset(pImg,0xFF,dwImgSize);

	memcpy(pImg,pHead,dwHdrSize);
	free(pHead);
	pHead = NULL;
	
        {
		FILE* pFile = fopen(pKernelInfo->szFileName, "r");
		if (NULL == pFile)
		{
			free(pImg);	
			return FALSE;
		}
	
		ALOGE("DownloadKernel nFileLen=%X",nFileLen);
		if ( nFileLen != fread(pImg+dwHdrSize, 1, nFileLen, pFile))
		{
			free(pImg);
			fclose(pFile);
			return FALSE;
		}
		fclose(pFile);
	}
	
		
	bRet = DownLoadBuf(nAddress, "KernelImg", pImg, dwImgSize);

	return bRet;
}

